#include <iostream>
#include <fstream>
#include <cassert>

#include "RegextoNFA.h"

using namespace std;

void analyze(const miniDFA &dfa, const string &input, const string &output)
{

    State *currentState = dfa.startState;
    State *nextState = nullptr;
    string buffer;
    vector<string> tokens; // 用于收集识别到的Token
    // 打开结果输出文件
    ofstream file(output);

    for (size_t i = 0; i < input.length(); ++i)
    {
        char c = input[i];
        if (c == ' ' || c == '\n' || c == '\r' || c == '\t') // 如果是空格、换行等分隔符，则跳过
        {
            continue;
        }
        if (c == '/' && input[i + 1] == '/') // 如果是注释，则跳到下一行
        {
            while (input[i] != '\n' && i < input.length())
            {
                i++;
            }
            continue;
        }
        InputCharType inputCharType = getInputCharType(c);
        auto it = currentState->transitions.find(inputCharType);

        if (it != currentState->transitions.end())
        {
            nextState = *(it->second.begin());
            buffer.push_back(c);

            if (nextState->isFinalState && i + 1 < input.length())
            { // 如果下一个状态是终止状态并且还有剩余字符
                char nextChar = input[i + 1];
                InputCharType nextInputCharType = getInputCharType(nextChar);
                auto nextIt = nextState->transitions.find(nextInputCharType); // 查找下一个状态的转换表中是否有对应的输入字符类型

                if (nextIt == nextState->transitions.end())
                { // 如果没有更多匹配的转换
                    // 输出识别到的单词符号和对应的类型
                    cout << buffer << "\t<" << getWordTypeName(nextState->wordType, buffer) << "," << getWordTypeContent(nextState->wordType, buffer) << ">" << endl;
                    file << buffer << "\t<" << getWordTypeName(nextState->wordType, buffer) << "," << getWordTypeContent(nextState->wordType, buffer) << ">" << endl;
                    buffer.clear();
                    currentState = dfa.startState;
                }
                else
                {
                    currentState = nextState; // 更新当前状态为下一个状态
                }
            }
            else
            {
                currentState = nextState; // 更新当前状态为下一个状态
            }
        }
        else
        { // 如果没有找到匹配的转换
            if (currentState->isFinalState)
            { // 如果当前状态是终止状态
                // 输出识别到的单词符号和对应的类型
                cout << buffer << "\t<" << getWordTypeName(currentState->wordType, buffer) << "," << getWordTypeContent(nextState->wordType, buffer) << ">" << endl;
                file << buffer << "\t<" << getWordTypeName(currentState->wordType, buffer) << "," << getWordTypeContent(nextState->wordType, buffer) << ">" << endl;
                buffer.clear();
            }
            else
            {
                // 如果当前状态不是终止状态
                // 输出无法识别的字符信息
                cout << "无法识别的字符: " << c << endl;
                file << "无法识别的字符: " << c << endl;

                buffer.clear();
            }
            currentState = dfa.startState; // 回到起始状态
            //--i;// 重新处理当前字符,还是跳过吧，这里可以添加错误处理
        }
    }
    // 处理最后一个字符，如果缓冲区不为空且当前状态是终止状态,对应第一个if里面的else
    if (!buffer.empty() && currentState->isFinalState)
    {
        cout << buffer << "\t<" << getWordTypeName(currentState->wordType, buffer) << "," << getWordTypeContent(nextState->wordType, buffer) << ">" << endl;
        file << buffer << "\t<" << getWordTypeName(currentState->wordType, buffer) << "," << getWordTypeContent(nextState->wordType, buffer) << ">" << endl;
    }
    file.close(); // 关闭文件
}

int main(int argc, char **argv)
{
    // 构建NFA
    RegextoNFA nfa = regexToNFA();
    // 打印NFA状态
    // printNFA(nfa);

    // NFA转换为DFA
    miniDFA dfa = nfaToDFA(nfa);
    // 打印DFA状态
    // printDFA(dfa);

    // DFA最小化
    miniDFA minimizedDFA = minimizeDFA(dfa);
    removeUnreachableStates(minimizedDFA);
    // printDFA(minimizedDFA);
    // cout<<"new state size: "<<minimizedDFA.states.size()<<endl;
    vector<string> inputs = {
        // R"(tests\sources\0.txt)",
        // R"(tests\sources\1.txt)",
        // R"(tests\sources\2.txt)",
        // R"(tests\sources\3.txt)",
        // R"(tests\sources\4.txt)",
        R"(tests\sources\test8.sy)",
    };

    vector<string> outputs_lexical = {
        // R"(output\result-lexical\0.txt)",
        // R"(output\result-lexical\1.txt)",
        // R"(output\result-lexical\2.txt)",
        // R"(output\result-lexical\3.txt)",
        // R"(output\result-lexical\4.txt)",
        R"(output\result-lexical\8lex.tsv)",
    };

    for (int i = 0; i < inputs.size(); i++)
    {
        const string &input = inputs[i];
        string content = readfile(input);
        analyze(minimizedDFA, content, outputs_lexical[i]);
        cout << "Processed: " << input << endl;
    }

    return 0;
}